package com.cykj.enterprise.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.cykj.common.dto.ResponseDTO;
import com.cykj.common.entity.*;
import com.cykj.common.utils.EmailValidateUtil;
import com.cykj.common.utils.FileCheckUtil;
import com.cykj.common.utils.SaTokenUtils;
import com.cykj.common.utils.SnowflakeUtil;
import com.cykj.common.utils.ValidateCodeUtil;
import com.cykj.enterprise.mapper.HrMapper;
import com.cykj.enterprise.mapper.PayMapper;
import com.cykj.enterprise.service.IHrService;
import com.cykj.enterprise.vo.HrVO;
import com.cykj.enterprise.vo.CompanyInfoVO;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @BelongsProject: smart_recruit_backend
 * @BelongsPackage: com.cykj.enterprise.service.impl
 * @Author: 蔡张君逸
 * @CreateTime: 2025-08-19 15:55
 * @Description: TODO
 * @Version: 1.0
 */
@Service
public class HrServiceImpl implements IHrService {
    static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    @Value("#${uploadFile}")
    String uploadFile;
    @Autowired
    HrMapper hrMapper;
    @Autowired
    RedisTemplate<String, Object> redisTemplate;
    @Autowired
    EmailValidateUtil emailValidateUtil;
    @Autowired
    PayMapper payMapper;
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    private SnowflakeUtil snowflakeUtil;

    @Value("${fileUploadPath.license}")
    private String licensePath;
    @Value("${fileUploadPath.prove}")
    private String provePath;
    @Value("${fileUploadPath.companyIcon}")
    private String companyIconPath;

    @Override
    public ResponseDTO hrLogin(String account, String password, String code, HttpSession httpSession) {
        LocalDateTime time = (LocalDateTime) httpSession.getAttribute("ban");
        if (time != null) {
            if (Duration.between(time,LocalDateTime.now()).toSeconds() < 30) {
                return ResponseDTO.error("账号密码错误超过五次，禁用登录30s");
            }else {
                httpSession.removeAttribute("ban");
            }
        }
        HrDO hrDO = hrMapper.hrLogin(account, password);
        String trueCode = (String) httpSession.getAttribute("hrCode");
        if (code.equals(trueCode)) {
            if (hrDO != null) {
                SaTokenUtils.saLogin("hr", hrDO.getHrId());
                if (httpSession.getAttribute("times") != null) {
                    httpSession.removeAttribute("times");
                }
                return ResponseDTO.success("登录成功");
            }else {
                if (httpSession.getAttribute("times") != null) {
                    httpSession.setAttribute("times", (int) httpSession.getAttribute("times") + 1);
                } else {
                    httpSession.setAttribute("times", 1);
                }
                if ((int) httpSession.getAttribute("times") >= 5) {
                    httpSession.setAttribute("ban", LocalDateTime.now());
                    httpSession.removeAttribute("times");
                    return ResponseDTO.error("连续输入账号或密码错误，禁止登录30s");
                }
                return ResponseDTO.error("账号或密码错误");
            }

        } else {
            return ResponseDTO.error("验证码错误");
        }
    }

    @Override
    public ResponseDTO getValidateCodeImage(HttpSession httpSession) {

        ValidateCodeUtil validateCodeUtil = new ValidateCodeUtil();
//        base64位图片
        String codeImage = validateCodeUtil.getRandomCodeImage();
//        正确验证码
        String code = validateCodeUtil.getCode();
//        存储验证吗
        httpSession.setAttribute("hrCode", code);

        return ResponseDTO.success(codeImage);
    }

    @Override
    public ResponseDTO register(HrVO hrVO, HttpSession httpSession) {
        String trueCode = (String) httpSession.getAttribute("emailCode");
        System.err.println(hrVO.getCode());
        if (hrVO.getCode().equals(trueCode)) {
            try {
                int res = hrMapper.register(hrVO);
                return ResponseDTO.success("注册成功");
            } catch (Exception e) {
                return ResponseDTO.error("重复的账号");
            }
        }
        return ResponseDTO.error("验证码错误");
    }

    @Override
    public ResponseDTO getLoginInfo(int hrId) {
        HrDO hrDO = hrMapper.getLoginInfo(hrId);
        return ResponseDTO.success(hrDO);
    }

    @Override
    public ResponseDTO updateInfo(HrDO hrDO) {
        try {
            int res = hrMapper.updateInfo(hrDO);
        } catch (Exception e) {
            return ResponseDTO.error("账号不可重复");
        }
        deleteHrInfoRedis(hrDO.getHrId());
        return ResponseDTO.success();
    }

    @Override
    public ResponseDTO getSubHrs(int companyId) {
        List<HrDO> hrDOList = hrMapper.getSubHrs(companyId);
        return ResponseDTO.success(new PageInfo<>(hrDOList));
    }

    @Override
    public ResponseDTO changeStatus(int hrId) {
        int res = hrMapper.changeStatus(hrId);
        return ResponseDTO.success();
    }

    @Override
    public ResponseDTO addSubHr(HrDO hrDO) {
        CompanyDO vipInfo = payMapper.getVipInfo(StpUtil.getLoginIdAsString());
        int num=hrMapper.countSubHr(hrDO);
        int max;
        if (LocalDateTime.parse(vipInfo.getVipEndTime(),formatter).compareTo(LocalDateTime.now())>0) {
             max=10;
        }
        else {
             max=5;
        }
        if (num>=max) {
            return ResponseDTO.error("已达上限");
        }
        try {
            int res = hrMapper.addSubHr(hrDO);
            return ResponseDTO.success();
        } catch (Exception e) {
            return ResponseDTO.error("账号重复");
        }
    }

    @Override
    public ResponseDTO reviseUserImg(MultipartFile imgFile) {
        //        1.存储
        uploadFile = uploadFile.replace("#", "");
//        得到尾缀
        String[] split = imgFile.getOriginalFilename().split("\\.");
        String end = split[split.length - 1];

        String name = StpUtil.getLoginId() + "." + end;
        File file = new File(uploadFile + "/" + name);
        String path = file.getAbsolutePath();
        try {
            imgFile.transferTo(new File(path));
//            imgFile.transferTo(new File(path));
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseDTO.error("上传文件失败");
        }
//        2.更改用户id对应的imgName
        int res = hrMapper.reviseImgName(StpUtil.getLoginId(), name);
        if (res > 0) {
            deleteHrInfoRedis(StpUtil.getLoginIdAsInt());
            return ResponseDTO.success();
        }
        return ResponseDTO.error("修改绑定路径失败");
    }

    //    获取user的在线简历
    @Override
    public ResponseDTO getUserOnlineResume(int userId) {
        if (redisTemplate.opsForValue().get("OnlineResume:" + userId) == null) {
            OnlineResumeDO onlineResumeDO = hrMapper.getUserOnlineResume(userId);
            redisTemplate.opsForValue().set("OnlineResume:" + userId, onlineResumeDO,30, TimeUnit.MINUTES);
            if (onlineResumeDO==null){
                return ResponseDTO.error("该用户没有在线简历");
            }
            return ResponseDTO.success(onlineResumeDO);
        } else {
//            System.err.println("返回redis在线简历");
            OnlineResumeDO onlineResumeDO = objectMapper.convertValue(redisTemplate.opsForValue().get("OnlineResume:" + userId),new TypeReference<OnlineResumeDO>() {});
            if (onlineResumeDO==null){
                return ResponseDTO.error("该用户没有在线简历");
            }
            return ResponseDTO.success(onlineResumeDO);
        }
    }

    @Override
    public UserDO getUserInfo(int userId) {
        int hrId = StpUtil.getLoginIdAsInt();
        if (redisTemplate.opsForValue().get("hrId:"+hrId+"userInfo:" + userId) != null) {
            return objectMapper.convertValue(redisTemplate.opsForValue().get("hrId:"+hrId+"userInfo:"+userId),new TypeReference<UserDO>() {});
        }
        UserDO userDO = hrMapper.getUserInfo(userId, hrId);
        redisTemplate.opsForValue().set("hrId:"+hrId+"userInfo:"+userId, userDO,3,TimeUnit.MINUTES);
        return userDO;
    }

    @Override
    public ResponseDTO hrCompanyCheck() {
        Integer hrId = StpUtil.getLoginIdAsInt();
        System.out.println(hrId);
        HrDO hrDO = hrMapper.hrCompany(hrId);
        if (hrDO != null) {
            return ResponseDTO.success(hrDO);
        }
        CompanyCheckDO companyCheckDO = hrMapper.hrCompanyCheck(hrId);
        if (companyCheckDO != null) {
            return ResponseDTO.success(companyCheckDO);
        }
        return ResponseDTO.success();
    }

    @Override
    public ResponseDTO submitCompanyData(CompanyInfoVO companyInfoVO) {
        MultipartFile license;
        MultipartFile prove;
        MultipartFile companyIcon;
        try {
            license = companyInfoVO.getLicense();
            prove = companyInfoVO.getProve();
            companyIcon = companyInfoVO.getCompanyIcon();
            FileCheckUtil.validateFile(license);
            FileCheckUtil.validateFile(prove);
            FileCheckUtil.validateFile(companyIcon);
        } catch (Exception e) {
            return ResponseDTO.error("文件不合法！");
        }
        fileDocumentExist();


        String fullLicense = null;
        String fullProve = null;
        String fullCompanyIcon = null;
        try {
            fullLicense = getFullFileName(license, licensePath);
            fullProve = getFullFileName(prove, provePath);
            fullCompanyIcon = getFullFileName(companyIcon, companyIconPath);
        } catch (Exception e) {
            return ResponseDTO.error("文件上传失败！");
        }

        companyInfoVO.setLicensePath(fullLicense);
        companyInfoVO.setProvePath(fullProve);
        companyInfoVO.setCompanyIconPath(fullCompanyIcon);
        companyInfoVO.setHrId(StpUtil.getLoginIdAsInt());
        Integer i = hrMapper.submitCompanyData(companyInfoVO);
        if (i == 0) {
            return ResponseDTO.error("审核数据提交失败！");
        }
        return ResponseDTO.success("上传成功！");
    }

    /**
     * @Description: 上传文件，并获取完整文件名（路径+文件名）
     * @Param: []
     * @return: java.lang.String
     */
    private String getFullFileName(MultipartFile file, String path) throws Exception {
        String[] split = file.getOriginalFilename().split("\\.");

        String suffix = split[split.length - 1];

        long newFileName = snowflakeUtil.nextId();

        String fullName = newFileName + "." + suffix;

        String fullPath = path + "/" + fullName;

        File file1 = new File(fullPath);
        String absolutePath = file1.getAbsolutePath();

        file.transferTo(new File(absolutePath));

        return fullPath;
    }

    /**
     * @Description: 判断文件夹是否存在
     * @Param: []
     * @return: void
     */
    private void fileDocumentExist() {
        File licenseDoc = new File(licensePath);
        if (!licenseDoc.exists()) {
            licenseDoc.mkdirs();
        }
        File proveDoc = new File(provePath);
        if (!proveDoc.exists()) {
            proveDoc.mkdirs();
        }

        File companyIconDoc = new File(companyIconPath);
        if (!companyIconDoc.exists()) {
            companyIconDoc.mkdirs();
        }
    }

    @Override
    public ResponseDTO emailValidateCode(String address, HttpSession httpSession) {
        ValidateCodeUtil validateCodeUtil = new ValidateCodeUtil();
        validateCodeUtil.getRandomCodeImage();
        String code = validateCodeUtil.getCode();
        httpSession.setAttribute("emailCode", code);
        try {
            emailValidateUtil.send(address, "验证码：" + code, "hr注册验证码");
            return ResponseDTO.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseDTO.error("发送验证码失败");
        }
    }

//修改名字头像后，清空一下聊天那里，负责个人信息的redis
    public void deleteHrInfoRedis(int hrId){
        redisTemplate.delete("hrSimplInfo:"+hrId);
    }
}